import arcpy
import subprocess
import os
import platform
import numpy
import sys
import datetime

overridden_log_path = None

def callGpTool(args):
    exe = os.path.join(os.path.dirname(__file__), "Bes.Swsp.GpTools.exe")

    addMessage("Preparing to launch " + exe)
    addMessage("Args: " + str(args)[1:-1])

    # copy args list so as not to alter original
    subargs = list(args)
    subargs.insert(0,exe)

    try:
        #subprocess.call(subargs)
        process = subprocess.Popen(subargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        status, error = process.communicate()
    except Exception:
        addMessage("Error launching GpTools: " + sys.exc_info()[0])
        return

    addMessage("GpTools status: " + status + "\n")
    if process.returncode != 0:
        addMessage("GpTools failed with error:\n" + str(error))
        #raise(Exception(error))
        sys.exit(1)

    addMessage("Returned from executable " + exe)
    return

def convertParametersToFullPathStrings(parameters):
    addMessage("Converting parameters to full catalog path...")
    args = []
    for p in parameters:
        arcpy.AddMessage("Checking parameter '" + p.name + "' (type= " + p.datatype + "): " + p.valueAsText)
        if p.datatype in ["Feature Layer", "Raster Layer"]:
            desc = arcpy.Describe(p.valueAsText)
            addMessage("Parameter '" + p.name + "' converted from " + p.valueAsText + " to " + desc.catalogPath)
            args.append(desc.catalogPath)
        else:
            args.append(p.valueAsText)
    return args


def gdalTranslate(inRaster, outRaster, outputType=None, noDataValue=None):

    gdalCommand = r'C:\Program Files\GDAL\gdal_translate.exe "{0}" "{1}"'.format(inRaster, outRaster)
    if outputType is not None:
        gdalCommand = gdalCommand + " -ot {0}".format(outputType)

    if noDataValue is not None:
        gdalCommand = gdalCommand + " -a_nodata {0}".format(noDataValue)


    addMessage("Calling: " + gdalCommand)
    process = subprocess.Popen(gdalCommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    status, error = process.communicate()
    print "GDAL status: " + status
    if process.returncode != 0:
        addMessage("GDAL failed with error:\n" + str(error))
        sys.exit(1)

    return

def tauD8Area(flowDir, rasterToAccumulate, outRaster, numProc=4):
    if rasterToAccumulate is None:
        taudemCommand = (r'mpiexec -n {0} AreaD8 -p "{1}" -ad8 "{2}" -nc'.format(numProc, flowDir, outRaster))
    else:
        taudemCommand = (r'mpiexec -n {0} AreaD8 -p "{1}" -ad8 "{2}" -wg "{3}" -nc'.format(numProc, flowDir, outRaster, rasterToAccumulate))
    addMessage("Calling TauDEM: " + taudemCommand)

    process = subprocess.Popen(taudemCommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    status, error = process.communicate()
    addMessage("TauDEM status: " + status)
    if process.returncode != 0:
        addMessage("TauDEM failed with error:\n" + str(error))
        sys.exit(1)

    return

def addMessage(message, log_file_path = None):

    if len(message) < 1000:
        arcpy.AddMessage(message)

    time_stamp = datetime.datetime.now().strftime('%x %X')
    full_message = "{0} - {1}".format(time_stamp, message)
    print full_message[0:min(len(full_message), 1000)]

    # Hack to get rawq scripts to output to build log without having to pass through logfile name
    if log_file_path is None and platform.node() == 'WS18325':
        script_dir = os.path.dirname(os.path.abspath(__file__))
        if script_dir.lower() == r'c:\swsp\scripts':
            log_file_path = r'C:\SWSP\Build\Swsp.Build.log'

    if log_file_path is None:
        script_dir = os.getcwd()
        log_file_path = os.path.join(script_dir, "Swsp.Build.log")

    if not overridden_log_path is None:
        log_file_path = overridden_log_path

    if not log_file_path is None:
        log_file = open(log_file_path, 'a')
        log_file.write(full_message + "\n")
        log_file.close()

    return

""" Values less than the lowest value in originalValues will be assigned the lowest value in newValues
    Values greater than the highest value in originalValues will be assigned the highest value in newValues

    """
def mapValues(inArray, originalValues, newValues):

    if len(originalValues) != len(newValues):
        raise Exception("Map values must be the same length")

    originalValues = numpy.sort(originalValues)
    newValues = numpy.sort(newValues)

    outArray =  numpy.interp(inArray, originalValues, newValues)

    return outArray

def CopyFieldFromFeatureClass(targetFc, targetJoinField, targetField, fromFc, fromJoinField, fromField, whereClause = None, prependString = ''):
    fieldType = u'String'
    targetFields = arcpy.ListFields(targetFc,targetField)
    if len(targetFields) == 0:
        sourceFields = arcpy.ListFields(fromFc, fromField)
        fieldType = sourceFields[0].type
        arcpy.AddField_management(targetFc, targetField, fieldType, sourceFields[0].precision, sourceFields[0].scale, sourceFields[0].length)
    else:
        fieldType = targetFields[0].type

    values={}
    with arcpy.da.SearchCursor(fromFc,[fromJoinField,fromField], whereClause) as cursor:
        for row in cursor:
            if row[0] != None:
                values[row[0]] = row[1]

    count = 0
    with arcpy.da.UpdateCursor(targetFc, [targetJoinField, targetField]) as cursor:
        for row in cursor:
            if row[0] in values:
                if values[row[0]] != None:
                    if fieldType == u'String':
                        row[1] = prependString + values[row[0]]
                    else:
                        row[1] = values[row[0]]
                    cursor.updateRow(row)
                    count += 1

    print "CopyFieldFromFeatureClass values copied: ", count

def IdentifyFeaturesFromTable(targetFc, targetJoinField, targetField, calcValue, fromFc, fromJoinField, targetWhereClause = None, fromWhereClause = None):
    if len(arcpy.ListFields(targetFc,targetField)) == 0:
        arcpy.AddField_management(targetFc, targetField, "TEXT","#","#",50)

    count = 0
    ids = set()
    with arcpy.da.SearchCursor(fromFc, fromJoinField, fromWhereClause) as cursor:
        for row in cursor:
            ids.add(row[0])
            count +=1
    print "Source features queried:", count

    count = 0

    with arcpy.da.UpdateCursor(targetFc, [targetJoinField, targetField], targetWhereClause) as cursor:
        for row in cursor:
            if row[0] in ids:
                row[1] = calcValue
                cursor.updateRow(row)
                count += 1
    print "Target features identified:", count


